package com.sc.nft.dao;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sc.nft.dto.OrderSettleDTO;
import com.sc.nft.entity.OrderSettle;
import com.sc.nft.entity.PayOrder;
import com.sc.nft.enums.*;
import com.sc.nft.mapper.ScOrderSettleMapper;
import com.sc.nft.util.OrderNoUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

import static com.sc.nft.util.OrderNoUtil.SETTLE_ORDER_PREFIX;

@Slf4j
@Repository
public class OrderSettleDao extends ServiceImpl<ScOrderSettleMapper, OrderSettle> {

    /**
     * 添加结算订单
     *
     * @return
     */
    public OrderSettle addOrderSettle(Long orderId, BigDecimal buyPrice, String orderNo, Long userId, PayOrder payOrder,
                                      WalletDetailTypeEnum sellType, BigDecimal settleAmount, SettleUserTypeEnum
                                              settleUserType, ExpenditureRecordTypeEnum expenditureRecordTypeEnum
            , BizTypeEnum bizTypeEnum, MarketLevelEnum marketLevelEnum) {
        OrderSettle orderSettle = new OrderSettle();
        orderSettle.setSettleNo(OrderNoUtil.getOrderSn(SETTLE_ORDER_PREFIX));
        orderSettle.setOrderId(orderId);
        orderSettle.setOrderAmount(buyPrice);
        orderSettle.setPayOrderId(payOrder.getId());
        orderSettle.setPayNo(payOrder.getTradeNo());
        orderSettle.setType(sellType);
        orderSettle.setSettleAmount(settleAmount);
        orderSettle.setStatus(SettleAccountStatusEnum.UNSETTLE);
        orderSettle.setPayMethod(payOrder.getPayType());
        orderSettle.setOrderNo(orderNo);
        orderSettle.setBizType(bizTypeEnum);
        orderSettle.setMarketLevel(marketLevelEnum);
        orderSettle.setExpenditureRecordType(expenditureRecordTypeEnum);
        //当前类型为商户(此处商户为公司商户号) 则用户id=0 结算时直接传递商户号
        orderSettle.setUserId(settleUserType.equals(SettleUserTypeEnum.MERCHANT) ? 0 : userId);
        //此字段只对杉德有作用
        orderSettle.setExpireTime(DateUtil.offsetDay(payOrder.getPayTime(), 60));
        orderSettle.setUserType(settleUserType);
        orderSettle.setPayChannel(payOrder.getChannel());

        this.save(orderSettle);
        return orderSettle;
    }


    /**
     * 确认结算
     *
     * @param orderSettle
     */
    public void settleOrder(OrderSettle orderSettle) {
        orderSettle.setStatus(SettleAccountStatusEnum.SETTLED);
        this.updateById(orderSettle);
    }


    /**
     * 取消结算
     *
     * @param orderSettle
     */
    public void cancellOrder(OrderSettle orderSettle) {
        orderSettle.setStatus(SettleAccountStatusEnum.CANCELLED);
        this.updateById(orderSettle);
    }

    /**
     * 批量查询用户待结算订单每次1000条数据
     *
     * @param payChannelEnum
     * @return
     */
    public List<OrderSettle> unSettleOrderForUser(PayChannelEnum payChannelEnum) {
        if (payChannelEnum.equals(PayChannelEnum.LL_PAY)) {
            return this.baseMapper.getUnsettleOrderByLLForUser();
        } else if (payChannelEnum.equals(PayChannelEnum.SAND)) {
            return this.baseMapper.getUnsettleOrderBySandForUser();
        } else {
            throw new RuntimeException("暂不支持");
        }
    }

    /**
     * 批量查询平台待结算订单每次1000条数据
     *
     * @param payChannelEnum
     * @return
     */
    public List<OrderSettle> unSettleOrderForPlat(PayChannelEnum payChannelEnum) {
        if (!payChannelEnum.equals(PayChannelEnum.LL_PAY) && !payChannelEnum.equals(PayChannelEnum.SAND)) {
            throw new RuntimeException("暂不支持");
        }
        return this.baseMapper.getSettleForPlat(payChannelEnum);
    }

    public List<OrderSettle> getUserFailedSettleOrder(Long userId) {
        LambdaQueryWrapper<OrderSettle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderSettle::getUserId, userId);
        queryWrapper.eq(OrderSettle::getStatus, SettleAccountStatusEnum.FAILED);
        return this.baseMapper.selectList(queryWrapper);
    }


    /**
     * 分页查询
     *
     * @param userId
     * @param payChannelEnum
     * @param statusEnum
     * @param pageNo
     * @param pageSize
     * @param startTime
     * @return
     */
    public IPage<OrderSettleDTO> flowPage(Long userId, PayChannelEnum payChannelEnum, SettleAccountStatusEnum statusEnum,
                                          int pageNo, int pageSize, String startTime) {
        LambdaQueryChainWrapper<OrderSettle> queryWrapper = new LambdaQueryChainWrapper<>(baseMapper);
        queryWrapper.eq(Objects.nonNull(payChannelEnum), OrderSettle::getPayChannel, payChannelEnum);
        queryWrapper.eq(Objects.nonNull(statusEnum) && !statusEnum.equals(SettleAccountStatusEnum.ALL),
                OrderSettle::getStatus, statusEnum);
        queryWrapper.eq(OrderSettle::getUserId, userId);
//        queryWrapper.ge(Objects.nonNull(startTime), OrderSettle::getCreateTime, startTime);
        if (Objects.nonNull(startTime)) {
            queryWrapper.last(" and MONTH(create_time)=MONTH('" + startTime + "')" + " order by id desc");
        } else {
            queryWrapper.orderByDesc(OrderSettle::getId);
        }


        return queryWrapper.page(new Page<>(pageNo, pageSize)).convert(flow -> {
            OrderSettleDTO orderSettleDTO = new OrderSettleDTO();
            BeanUtil.copyProperties(flow, orderSettleDTO);
            return orderSettleDTO;
        });
    }

}
